這應該是大家學design pattern第一個遇到的pattern吧,這個pattern有兩個角色
簡單說就是透過Factory來生產Product,client只需要告訴Factory,我要一個什麼Product,然後就得到他要的Product了。
架構圖長這樣:
我現在要去吃pizza了,所以需要定義:
當然都要是AbstractClass 或 interface,不應該把實作內容直接寫在這邊,物件導向語言的其中一個守則:針對介面寫程式,不是針對實踐方法寫程式
宣告Factory
public abstract class PizzaStore {
public abstract Pizza createPizza(String type);
public Pizza orderPizza(String type) { // client只要呼叫這個method就好
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
宣告Product
package com.example.designpattern.creational.factory_method.example2;
public abstract class Pizza {
String name;
String dough;
String sauce;
// method都不是宣告為abstract,如果subClass不用客製,就不用override
void prepare() {
System.out.println("Preparing: " + name + ", " + dough + ", " + sauce );
System.out.println("Tossing dough...");
};
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cutting pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
}
有了Factory跟Product後,就可以繼承他們來寫concreteClass了
先寫Factory,NYPizzaStore
package com.example.designpattern.creational.factory_method.example2;
public class NYPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
// 這間PizzaStore可以生產兩種Pizza
if("cheese".equals(type)) {
pizza = new NYCheesePizza();
} else if ("sausage".equals(type)) {
pizza = new NYSausagePizza();
}
return pizza;
}
@Override
public Pizza orderPizza(String type) {
return super.orderPizza(type);
}
}
再來是Product,第一種Product NYCheesePizza
package com.example.designpattern.creational.factory_method.example2;
public class NYCheesePizza extends Pizza {
String name = "NYCheesePizza";
String dough = "crispy";
String sauce = "cheese sauce";
@Override
void prepare() {
System.out.println("Amazing~~~ " + name +" , " + dough + " , " + sauce);
}
@Override
void bake() {
System.out.println("Bake for 15 minutes at 400");
}
@Override
void cut() {
System.out.println("Cutting pizza into 8 slices");
}
}
第二種Prodcut NYSausaePizze
package com.example.designpattern.creational.factory_method.example2;
public class NYSausagePizza extends Pizza {
String name = "NY Sausage pizze";
String dough = "Thick";
String sauce = "Marinara sauce";
@Override
void prepare() {
System.out.println(name +" , " + dough + " , " + sauce);
}
}
Client 要來點pizza了
package com.example.designpattern.creational.factory_method.example2;
public class PizzaClient {
public static void main(String[] args) {
// 進入NYPizzaStore
PizzaStore pizzaStore = new NYPizzaStore();
// 我要cheese pizza,啪,cheesePizza
Pizza cheesePizza = pizzaStore.orderPizza("cheese");
System.out.println("---------------");
// 我要sausage pizza,啪,sausagePizza
Pizza sausagePizza = pizzaStore.orderPizza("sausage");
}
/*
output:
Amazing~~~ NYCheesePizza , crispy , cheese sauce
Bake for 15 minutes at 400
Cutting pizza into 8 slices
Place pizza in official PizzaStore box
---------------
NY Sausage pizze , Thick , Marinara sauce
Bake for 25 minutes at 350
Cutting pizza into diagonal slices
Place pizza in official PizzaStore box
*/
}
https://refactoring.guru/design-patterns/factory-method
https://www.oreilly.com/library/view/head-first-design/0596007124/